﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;


namespace AdvancedMap
{
    
    public abstract class XmlSerializable
    {
        public virtual void Save(string path)
        {
            try
            {
                bool checkDir = CheckDirectory(path);
                StreamWriter w = new StreamWriter(path);
                XmlSerializer s = new XmlSerializer(this.GetType());
                s.Serialize(w, this);
                w.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine("Error in Save()");
                Console.WriteLine(e.ToString());
                Console.WriteLine(e.Message.ToString());
                Console.WriteLine(e.StackTrace.ToString());
            }
        }

        public virtual T Load<T>(string path) where T: class
        {
            T result;
            try
            {
                if (File.Exists(path))
                {
                    XmlSerializer deserializer = new XmlSerializer(typeof(T));
                    TextReader textReader = new StreamReader(path);
                    result = (T) deserializer.Deserialize(textReader);
                    textReader.Close();
                    return result;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error in Load()");
                Console.WriteLine(e.ToString());
                Console.WriteLine(e.Message.ToString());
                Console.WriteLine(e.StackTrace.ToString());
            }
            return null;
        }

        public enum ColorFormat
        {
            NamedColor,
            ARGBColor
        }

        public string SerializeColor(Color color)
        {
            if (color.IsNamedColor)
                return string.Format("{0}:{1}",
                    ColorFormat.NamedColor, color.Name);
            else
                return string.Format("{0}:{1}:{2}:{3}:{4}",
                    ColorFormat.ARGBColor,
                    color.A, color.R, color.G, color.B);
        }

        public Color DeserializeColor(string color)
        {
            byte a, r, g, b;

            string[] pieces = color.Split(new char[] { ':' });

            ColorFormat colorType = (ColorFormat)
                Enum.Parse(typeof(ColorFormat), pieces[0], true);

            switch (colorType)
            {
                case ColorFormat.NamedColor:
                    return Color.FromName(pieces[1]);

                case ColorFormat.ARGBColor:
                    a = byte.Parse(pieces[1]);
                    r = byte.Parse(pieces[2]);
                    g = byte.Parse(pieces[3]);
                    b = byte.Parse(pieces[4]);

                    return Color.FromArgb(a, r, g, b);
            }
            return Color.Empty;
        }

        public struct XmlFont
        {
            public string FontFamily;
            public GraphicsUnit GraphicsUnit;
            public float Size;
            public FontStyle Style;

            public XmlFont(Font f)
            {
                FontFamily = f.FontFamily.Name;
                GraphicsUnit = f.Unit;
                Size = f.Size;
                Style = f.Style;
            }

            public Font ToFont()
            {
                return new Font(FontFamily, Size, Style,
                    GraphicsUnit);
            }
        }
        protected static XmlFont SerializeFont(Font font)
        {
            return new XmlFont(font);
        }

        protected static Font DeserializeFont(XmlFont font)
        {
            return font.ToFont();
        }

        private static bool CheckDirectory(string strFilePath)
        {
            try
            {
                int nFindSlashPos = strFilePath.Trim().LastIndexOf("\\");
                string strDirectoryname =
                           strFilePath.Trim().Substring(0, nFindSlashPos);

                if (false == Directory.Exists(strDirectoryname))
                    Directory.CreateDirectory(strDirectoryname);
                return true;
            }
            catch (Exception)
            {
                return false;

            }
        }


    }



    public class PathEditor : UITypeEditor
    {
        //A class to hold our OpenFileDialog Settings
        public class OfdParamsAttribute : Attribute
        {
            public OfdParamsAttribute(string sFileFilter, string sDialogTitle)
            {
                m_Filter = sFileFilter;
                m_Title = sDialogTitle;
            }

            //The File Filter(s) of the open dialog
            private string m_Filter;
            public string Filter
            {
                get { return m_Filter; }
                set { m_Filter = value; }
            }

            //The Title of the open dialog
            private string m_Title;
            public string Title
            {
                get { return m_Title; }
                set { m_Title = value; }
            }
        }

        //The default settings for the file dialog
        private OfdParamsAttribute m_Settings = new OfdParamsAttribute("All Files (*.*)|*.*", "Open");
        public OfdParamsAttribute Settings
        {
            get { return m_Settings; }
            set { m_Settings = value; }
        }

        //Define a modal editor style and capture the settings from the property
        public override UITypeEditorEditStyle GetEditStyle(
                    ITypeDescriptorContext context)
        {
            if (context == null || context.Instance == null)
                return base.GetEditStyle(context);

            //Retrieve our settings attribute (if one is specified)
            OfdParamsAttribute sa = (OfdParamsAttribute)context.PropertyDescriptor.Attributes[typeof(OfdParamsAttribute)];
            if (sa != null)
                m_Settings = sa; //Store it in the editor
            return UITypeEditorEditStyle.Modal;
        }

        //Do the actual editing
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            if (context == null || context.Instance == null || provider == null)
                return value;

            //Initialize the file dialog with our settings
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = m_Settings.Filter;
            dlg.CheckFileExists = true;
            dlg.Title = m_Settings.Title;

            //Find if the current value is legitimate
            string filename = (string)value;
            if (!File.Exists(filename))
                filename = null;

            //Preselect the existing file (if it exists)
            dlg.FileName = filename;
            //Display the dialog and change the value if confirmed
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                filename = dlg.FileName;
            }
            return filename;
        }
    }

                                            
}
